package com.far.permisions.rule.base;

import com.far.permissions.rule.RuleConfigProvider;
import com.far.permissions.rule.RuleValueConvertor;
import com.far.permissions.bean.persistence.ColumnRule;
import com.far.permissions.bean.RuleResult;
import com.far.permissions.bean.persistence.TableRule;
import com.far.permissions.enums.Mode;
import com.far.permissions.enums.State;
import lombok.extern.slf4j.Slf4j;
import lombok.var;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Slf4j
public class RuleResultInvoker {
    private final RuleConfigProvider tableRuleProvider;
    private final Map<String, RuleValueConvertor> valueActuatorMap = new ConcurrentHashMap<>();

    public RuleResultInvoker(RuleConfigProvider tableRuleProvider) {
        this.tableRuleProvider = tableRuleProvider;
    }

    public void addValueActuator(RuleValueConvertor valueActuator) {
        valueActuatorMap.putIfAbsent(valueActuator.getType(), valueActuator);
    }

    public List<RuleResult> getTablesRuleResult(Set<String> tableNames) {
        var result = new ArrayList<RuleResult>();
        List<TableRule> rulesByTables = tableRuleProvider.getRulesByTables(tableNames);
        for (TableRule rulesByTable : rulesByTables) {
            String table = rulesByTable.getTable();
            List<RuleResult> ruleResults = rulesByTable.getColumnRules().stream()
                    .filter((columnRule -> State.ENABLE.name().equals(columnRule.getState())))
                    .map((columnRule -> toRuleResult(columnRule, table))).collect(Collectors.toList());
            result.addAll(ruleResults);
        }
        return result;
    }

    private RuleResult toRuleResult(ColumnRule columnRule, String table) {
        RuleResult ruleResult = new RuleResult();
        ruleResult.setMode(Mode.valueOf(columnRule.getMode()));
        ruleResult.setColumn(columnRule.getColumn());
        ruleResult.setTable(table);
        try {
            RuleValueConvertor valueActuator = valueActuatorMap.get(columnRule.getType());
            if (valueActuator == null) {
                return null;
            }
            ruleResult.setValue(valueActuator.convert(columnRule.getValue()));
        } catch (Exception e) {
            log.error("getValue fail", e);
            return null;
        }
        return ruleResult;
    }
}
